Back to homepage

KDE Dolphin plugin to delete JPEG and RAW files simultaneously

2025-11-23

My camera takes pictures in jpeg and raw format simultaneously but when I store the pictures, I don´t like to have the raw and jpeg files in the same folder. When browsing through an image folder images with raw's and jpegs, an image viewer visits each image twice. And the raw version takes a lot of time to load. Also it just doesn´t look tidy.

So I put the raw files in a subfolder named raw, but this creates a problem. When I load files from the camera onto my pc, I want to sift through them and delete any duplicates, blanks, out-of-focus shots, boring shots, etc. But when browsing and deleting in the jpeg folder, the raw files are not deleted along with the jpegs.

Raw files in a seperate subfolder in 
        the Dolphin file manager

I use the KDE desktop so I built something that can delete jpegs and raw files at the same time from the right click menu in Dolphin. I think it turned out pretty well. Here is the python code:

DeleteJPEGandRAW.py

import sys
import argparse
import os.path
import logging
import logging.handlers as handlers
from send2trash import send2trash

raw_exts = ['.3fr','.ari','.arw','.bay','.braw','.crw','.cr2','.cr3','.cap','.data','.dcs','.dcr','.dng','.drf','.eip','.erf','.fff','.gpr','.iiq','.k25','.kdc','.mdc','.mef','.mos','.mrw','.nef','.nrw','.obm','.orf','.pef','.ptx','.pxn','.r3d','.raf','.raw','.rwl','.rw2','.rwz','.sr2','.srf','.srw','.tif','.x3f','.3FR','.ARI','.ARW','.BAY','.BRAW','.CRW','.CR2','.CR3','.CAP','.DATA','.DCS','.DCR','.DNG','.DRF','.EIP','.ERF','.FFF','.GPR','.IIQ','.K25','.KDC','.MDC','.MEF','.MOS','.MRW','.NEF','.NRW','.OBM','.ORF','.PEF','.PTX','.PXN','.R3D','.RAF','.RAW','.RWL','.RW2','.RWZ','.SR2','.SRF','.SRW','.TIF','.X3F']

inputparser = argparse.ArgumentParser(description='Parse input arguments')
inputparser.add_argument('-infile', type=str)
inputparser.add_argument('-rawdir', type=str, nargs='?', default='raw')
inputparser.add_argument('-logfile', type=str, nargs='?', default='DeleteJPEGandRAW.log')
inputargs = inputparser.parse_args()

logger = logging.getLogger('DeleteJPEGandRAW')
logger.setLevel(logging.INFO)

log_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

log_handler = handlers.RotatingFileHandler(inputargs.logfile, maxBytes=1048576, backupCount=1)
log_handler.setLevel(logging.INFO)
log_handler.setFormatter(log_formatter)

logger.addHandler(log_handler)

if not os.path.isfile(inputargs.infile):
    msg_error = f'Input file {inputargs.infile} not found.'
    logger.error(msg_error)
    sys.exit(msg_error)

if not (os.path.splitext(inputargs.infile)[1]).lower() == '.jpg':
    msg_error = f'Input file {inputargs.infile} is not a jpeg file.'
    logger.error(msg_error)
    sys.exit(msg_error)

dir_main = os.path.dirname(inputargs.infile)
dir_raw = os.path.join(dir_main, inputargs.rawdir)
base_filename = os.path.splitext(os.path.basename(inputargs.infile))[0]

if not os.path.exists(dir_raw):
    msg_error = f'Raw directory {dir_raw} not found'
    logger.error(msg_error)
    sys.exit(msg_error)

raw_file_found = False

for ext in raw_exts:
    rawfile = os.path.join(dir_raw, base_filename + ext)
    if os.path.isfile(rawfile):
        raw_file_found = True
        logger.info(f'Deleting {rawfile} and {inputargs.infile}')
        send2trash([rawfile, inputargs.infile])
        break
        
if not raw_file_found:
    logger.info(f'No raw file found for {inputargs.infile}. Deleting JPEG only.')
    send2trash(inputargs.infile)
        

It uses the Send2Trash library to delete files. Writing the delete logic natively for Linux would have been better, but this was faster :P I should rewrite that someday to get rid of the dependency. I used a cross platform library for file deletion because the plan was to also make it work in Windows explorer. The script actually works in Windows but I could not get an entry for it in the Windows 11 explorer context menu to work and gave up trying pretty quickly because I don´t really use it in Windows anyway.

(Whenever I write "It works" in this post. I mean it works on my machine :D)

So the script takes an input file as an argument. Optionally you can tell it where to put its log file and the name of the subdirectory where the raw files live. So how to get this to work in Dolphin, I hear you ask. Well I found out I needed to create something called a service menu.

Let's say the script is located in /home/user/Documents/python/. Following the instructions in the KDE developer docs, I created a .desktop file in /home/user/.local/share/kio/servicemenus/. This what it looks like:

delete-jpeg-and-raw.desktop

[Desktop Entry]
Type=Service
MimeType=image/jpeg;
Actions=deleteJPEGandRAW;

[Desktop Action deleteJPEGandRAW]
Name=Delete JPEG and RAW
Icon=layer-delete
Exec=/usr/bin/python3 
/home/user/Documents/python/DeleteJPEGandRaw/DeleteJPEGandRAW.py -infile "%u" -logfile "/home/user/Documents/python/DeleteJPEGandRaw/DeleteJPEGandRAW.log"
        

The "MimeType=image/jpeg;" indicates that the menu item should only be shown when right clicking a jpeg file. And of course the "Exec=...." contains the command to be executed. In the command line, the placeholder "%u" gets replaced with the url of the file that was right clicked.

And This is the result:

Dolphin context menu with option to 
        Delete JPEG and RAW file.

It also works when selecting multiple image files by the way.